package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.zzyl.constant.SuperConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.vo.ResourceVo;
import com.zzyl.vo.TreeItemVo;
import com.zzyl.vo.TreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    @Override
    public List<ResourceVo> list(ResourceDto resourceDto) {
        if (ObjectUtil.isNotEmpty(resourceDto.getParentResourceNo())) {
            resourceDto.setParentResourceNo(NoProcessing.processString(resourceDto.getParentResourceNo()));
        }
        List<Resource> resourceList = resourceMapper.list(resourceDto);
        return BeanUtil.copyToList(resourceList, ResourceVo.class);
    }

    @Override
    public TreeVo resourceTree(ResourceDto resourceDto) {
        ResourceDto dto = ResourceDto.builder()
                .parentResourceNo(NoProcessing.processString(SuperConstant.ROOT_PARENT_ID))
                .resourceType(SuperConstant.MENU)
                .build();

        List<Resource> resourceList = resourceMapper.list(dto);
        if (ObjectUtil.isEmpty(resourceList)) {
            throw new RuntimeException("菜单数据为空");
        }

        List<TreeItemVo> treeItemVoList = new ArrayList<>();

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setIdKey("label");
        List<Tree<String>> treeList = TreeUtil.build(resourceList, SuperConstant.ROOT_PARENT_ID, treeNodeConfig, (treeNode, treeItem) -> {
            treeItem.setName(treeNode.getResourceName());
            treeItem.setId(treeNode.getResourceNo());
            treeItem.setParentId(treeNode.getParentResourceNo());
        });
        List<TreeItemVo> childrenTreeItemVoList = BeanUtil.copyToList(treeList, TreeItemVo.class);
        // 6.由于没有根节点，构建跟节点信息
        TreeItemVo treeItemVo = TreeItemVo.builder().id(SuperConstant.ROOT_PARENT_ID).label("智慧养老院").children(childrenTreeItemVoList).build();
        // 7.封装到树形集合中
        treeItemVoList.add(treeItemVo);
        // 数据返回
        return TreeVo.builder().items(treeItemVoList).build();
    }

    @Override
    public void createResource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        // 同步父资源状态和子资源状态一致
        Resource parentResource = resourceMapper.selectByParentResourceNo(resourceDto.getParentResourceNo());
        resource.setDataState(parentResource.getDataState());

        // 添加子资源编号
        String resourceNo = createResourceNo(resource);
        resource.setResourceNo(resourceNo);

        // 调用新增mapper接口
        resourceMapper.insert(resource);
    }

    private String createResourceNo(Resource resource) {
        /**
         * 1、如果是菜单，以及父资源编号是否大于三级，说白就是暂时只支持最多三级菜单，不能创建四级菜单
         */
        if (resource.getResourceType().equals("m") &&
                NoProcessing.processString(resource.getParentResourceNo()).length() / 3 == 4) {
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        // 2.查询父资源编号下是否包含子资源
        // 找父节点是否有儿子
        List<Resource> resourceList = resourceMapper.selectChildrenByParentResourceNo(resource.getParentResourceNo());

        if (ObjectUtil.isEmpty(resourceList)) {
            // 3.父资源编号下没有下属节点，则新增  100 001 001 001 000--->新增下属节点100 001 001 001 001
            return NoProcessing.createNo(resource.getParentResourceNo(), false);
        } else {
            // 4.有下属节点，则在原有基础上追加 100 001 001 001 001--->追加之后，100 001 001 001 002
            // 要先获取下属节点中的最大值
            Long maxNo = resourceList.stream().map(resource1 -> {
                return Long.valueOf(resource1.getResourceNo());
            }).max(Comparator.comparing(Long::intValue)).get();
            return NoProcessing.createNo(String.valueOf(maxNo), true);
        }
    }
}
